package com.gj.common.annmapper;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.gj.common.utils.util.BeanToMapUtil;
import com.gj.common.utils.util.MyBatisReflectUtil;
import com.gj.common.utils.util.PageBean;
import com.gj.common.utils.util.PageList;


/**
 * 注：本类所执行sql时的封装建议安全sql占位如#{pwd}，也可以非占位，但自己要处理好，详见如下解释
 *MybatisBaseDaoCRUD基接口
 * @param <T> 处理的POJO对象
 *   公共方法使用注解实现，较简便
 *   * 为处理sql安全和严谨
 * 1、建议使用占位符#{key},如使用${key}或使用通用sql语句查询，请自行过滤非法字符
 * 2、建议使用<![CDATA[#{key}]]>,例：select * from sys_user  where email=<![CDATA[#{email}]]> and pwd=<![CDATA[#{pwd}]]>
 * 可以处理“‘”、“""”区分的问题
 * 3、模糊查询请使用自定义动态sql,进行判断和拼接可安全的sql，注意like 取值使用${key}
 * 4、排序字段desc,asc，模糊like,分页标识如 limit,top  均使用${key}
 * 5、此支持最强大的script动态构建sql脚本，如果使用熟练完全可取代xml mapping映射的方法
 */
@Repository
public  class MybatisBaseDaoCRUD<T>{
	@Autowired
	private BaseMapperCRUD bmc;
	
	public  BaseMapperCRUD<T> getBaseMapperCRUD() {
		return this.bmc;
	}
 
	/**
	   * @Description: 通用id实体删除
	   * @param  Any
	   */
	 @Transactional
	 public int deleteById(String id){
		 Class clazz=getEntityClass();
		 return getBaseMapperCRUD().deleteById(clazz, id);
	 }
	 
		/**
	   * @Description: 通用id实体删除
	   * @param  Any
	   */
	 @Transactional
	 public int deleteById(Class clz,String id){
		 return getBaseMapperCRUD().deleteById(clz, id);
	 }
	 
		/**
	   * @Description: 通用实体删除
	   * @param  Any
	   */
	 @Transactional
	 public int deleteObject(T entity){
		 
		 return getBaseMapperCRUD().delete(entity);
	 }
	  /**
	   * @Description: 通用实体保存
	   * @param  Any
	   */
	    @Transactional
	    public int saveObject(T entity){
	    	return getBaseMapperCRUD().insert(entity);
	    }
	    /**保存对象返回持久化对象
	     * @Description: 通用实体保存
	     * @param  Any
	     */
	    @Transactional
	    public Object saveObject2Object(T entity){
	    	Map m=getBaseMapperCRUD().save(entity);
	    	if(m!=null){
	    		try {
					return BeanToMapUtil.convertMap(entity.getClass(), m);
				} catch (Exception e) {
					e.printStackTrace();
					return null;
				}
	    	}
			return null;
	    }
	    
	  /**
	   * @Description: 通用实体更新
	   * @param  Any
	   */
	  @Transactional
	  public int updateObject(T entity){
		  return getBaseMapperCRUD().update(entity);
	  }
	  
	 
	  /**
	   * /**
	  delete from sys_user where data.id='784972358981328902'
	   * @Description: 执行sql
	   * @param sql
	   * @param params
	   * @return
	   */
	  @Transactional
	  public int executeSql(String sql,Map data){
		  return getBaseMapperCRUD().excuteBySql(sql, data);
	  }
	  /**
	   * @Description: 占位或非占位查询sql的查询唯一记录
	  * @param  设定
	  * @author 作者 jacking 
	  * @date 2017-6-17 下午4:05:05 
	  * @return
	   */
	  public Object findBySqlUniqueObject( String sql , Class clz ,Map params){
	  		try {
				Map map=getBaseMapperCRUD().findBySqlUnique(sql, params);
				if(map!=null&&clz!=null&&(!clz.getName().equals(Map.class.getName())&&!clz.getName().equals(HashMap.class.getName()))){
					return BeanToMapUtil.convertMap(clz, map);
				}else{
					return map;
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return  null;
			}
	  	}
	  	/**
	  	 * 查询单表实体列表
	  	 * @param clz
	  	 * @return
	  	 */
	    public List findAll(Class clz){
	    	List lst=new ArrayList<>();
	  		try {
	  			List<Map> l=getBaseMapperCRUD().selectAll(clz);
	  			for(Map map:l){
  					if(map!=null){
  						Object o=BeanToMapUtil.convertMap(clz, map);
  						lst.add(o);
  					}
				}
	  			return lst;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return  null;
			}
	  	}
	    /**
	     * 根据不同的sql,参数，返回类型，灵活转换查询返回列表
	     * @param sql
	     * @param clz
	     * @param param
	     * @return
	     */
	    public List findAll(String sql,Class clz,Map param){
	    	List lst=new ArrayList<>();
	  		try {
	  			List<Map> l=getBaseMapperCRUD().findBySqlMore(sql, param);
	  			if(clz!=null&&(!clz.getName().equals(Map.class.getName())&&!clz.getName().equals(HashMap.class.getName()))){
	  				for(Map map:l){
	  					if(map!=null){
	  						Object o=BeanToMapUtil.convertMap(clz, map);
	  						lst.add(o);
	  					}
					}
	  			}else{
	  				lst=l;
	  			}
	  			return lst;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return  null;
			}
	  	}
	    /**
	     * 泛型获取实体，根据主键查询唯一
	     * @param clz
	     * @param id
	     * @return
	     */
	    public Object findById(String id){
	    	Class clz=getEntityClass();
	    	Map m=getBaseMapperCRUD().selectById(clz, id);
	    	Object o=null;
	    	if(null!=null){
	    		try {
					o=BeanToMapUtil.convertMap(clz, m);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	    	}
	  		return o;
	  	}
	    /**
	     * 根据主键查询唯一
	     * @param clz
	     * @param id
	     * @return
	     */
	    public Object findById(Class clz,String id){
	    	Map m=getBaseMapperCRUD().selectById(clz, id);
	    	Object o=null;
	    	if(!clz.getName().equals(Map.class.getName())&&!clz.getName().equals(HashMap.class.getName())){
	    		try {
					o=BeanToMapUtil.convertMap(clz, m);
				} catch (Exception e) {
					
					e.printStackTrace();
				}
	    		
	    	}else{
	    		o=m;
	    	}
	    	
	  		 return o;
	  	 
	  	}
	    
	    /**
	     * 根据实体类型，字段和值查询,条件可能and || or
	     * @param clz
	     * @param id
	     * @return
	     */
	    public List findByProperty(Class clz,Map param,boolean isAndOr){
	    	List lst=new ArrayList<>();
	    	List l=getBaseMapperCRUD().selectByProperty(clz, param,isAndOr);
	    	if(lst!=null&&lst.size()>0){
	    		if(clz!=null&&(!clz.getName().equals(Map.class.getName())&&!clz.getName().equals(HashMap.class.getName()))){
	    			for(Object o:l){
						Map m=new HashMap();
	    				try {
    						o=BeanToMapUtil.convertMap(clz, m);
    						lst.add(o);
						} catch (Exception e) {
							e.printStackTrace();
							return lst;
						}
					}
	    		}else {
	    			lst=l;
	    		}
	    		
	    	}
	  		return lst;
	  	 
	  	}
	    
		/**
		 * 根据实体类型，字段和值查询，like查询 ，条件可能and || or
		 * @param clazz
		 * @param param
		 * @param isAndOr
		 * @return
		 */
		public List selectLikeByProperty(Class clazz,Map param,boolean isAndOr){
			return  getBaseMapperCRUD().selectLikeByProperty(clazz, param, isAndOr);
		}
		
	 
	  /**
	   * 
	   * @Description: 占位或非占位sql查询记录,
	  	* @Description: TODO(描述) 
	  	* @param  设定
	  	* @author 作者 jacking 
	  	* @date 2017-6-17 下午4:05:37 
	  	* @return
	  	 */
	  public List findBySql(String sql, Class clz ,Map  params){
	  		List lst=new ArrayList<>();
            try {
				List<Map> l=getBaseMapperCRUD().findBySqlMore(sql, params);
				if(null!=clz&&(!clz.getName().equals(Map.class.getName())&&!clz.getName().equals(HashMap.class.getName()))){
					for(Map map:l){
						if(map!=null){
							Object o=BeanToMapUtil.convertMap(clz, map);
							lst.add(o);
						}
					}
				}else{
					lst=l;
				}
			} catch (Exception e) {
				e.printStackTrace();
				return lst;
			}
            return lst;
	  	}
	  /**
	   * @Description: 查询 ：执行存储过程
	  	 * * callsql:
		 * 例：@Select("call  procedureName()")
		 * call procedureName(#{pojo.totalNum,jdbcType=INTEGER,mode=OUT},#{pojo.tableName,jdbcType=STRING,mode=IN},#{pojo.conditions,jdbcType=STRING,mode=IN})
	  	* @Description: TODO(描述) 
	  	* @param  设定
	  	* @author 作者 jacking 
	  	* @date 2017-6-17 下午3:57:57 
	  	* @return
	  	 */
	  public Object findByCallSql2Object(String callSql,Class clz, Map params){
	  			if(clz!=null&&(clz.getName().equals(List.class.getName())||clz.getName().equals(ArrayList.class.getName()))){
	  				List lst = getBaseMapperCRUD().findByCallSql2List(callSql,params);
	  				return lst;
	  			}else if(null!=clz&&(clz.getName().equals(Map.class.getName())||clz.getName().equals(HashMap.class.getName()))){
	  				Map  m=getBaseMapperCRUD().findByCallSql2Map(callSql, params);
	  				return m;
	  			}else{
	  				return null;
	  			}
	  	}
	    /**
		   * @Description: 执行存储过程
		  	 * * callsql:
			 * 例：@Select("call  procedureName()")
			 * call procedureName(#{pojo.totalNum,jdbcType=INTEGER,mode=OUT},#{pojo.tableName,jdbcType=STRING,mode=IN},#{pojo.conditions,jdbcType=STRING,mode=IN})
		  	* @Description: TODO(描述) 
		  	* @param  设定
		  	* @author 作者 jacking 
		  	* @date 2017-6-17 下午3:57:57 
		  	* @return
		  	 */
		  	@Transactional
		  public int excuteByCallSql(String callSql,Map params){
		  			 return getBaseMapperCRUD().excuteByCallSql(callSql, params);
		  	}
	  /**
	   * @Description: 占位或非占位sql，自行类型转换的分页查询
		  	* @param  设定
		  	* @author 作者 jacking 
		  	* @date 2017-6-17 下午4:06:35 
		  	* @return
		  	 */
	   public PageList findBySqlForPageList( String sql, Class clz,PageBean pageBean, Map params) {
	  		List lst=new ArrayList<>();
	  		try {
				if(null!=pageBean){
					Page  p=PageHelper.startPage(pageBean.getPage(),pageBean.getPageSize()); //开始分页
					List<Map> l=getBaseMapperCRUD().findBySqlMore(sql, params);
				    if(null!=clz&&(!clz.getName().equals(Map.class.getName())&&!clz.getName().equals(HashMap.class.getName()))){
				    	for(Map map:l){
				    		if(map!=null){
				    			Object o=BeanToMapUtil.convertMap(clz, map);
				    			lst.add(o);
				    		}
				    	}
				    }else{
				    	lst=l;
				    }
				   pageBean=new PageBean(p.getTotal(), p.getPageNum(), p.getPageSize());
				}else{
					List<Map> l=getBaseMapperCRUD().findBySqlMore(sql, params);
				    if(null!=clz&&(!clz.getName().equals(Map.class.getName())&&!clz.getName().equals(HashMap.class.getName()))){
				    	for(Map map:l){
				    		if(map!=null){
				    			Object o=BeanToMapUtil.convertMap(clz, map);
				    			lst.add(o);
				    		}
				    	}
				    }else{
				    	lst=l;
				    }
				   pageBean=new PageBean();
				}
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
	  		return new PageList(lst, pageBean);
	  	}
	  	/**
	  	 * 根据继承获取泛型的实体
	  	 * @return
	  	 */
	  	public Class<T> getEntityClass(){
			Class<T> entityClass = (Class<T>)((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
			return entityClass;
		}
	  	/**
	  	 * 根据Class对象获取表名称
	  	 * @param clz
	  	 * @return
	  	 */
	  	public static String  tableName(Class clz){
				try {
					return MyBatisReflectUtil.tablename(clz.newInstance());
				} catch (InstantiationException | IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return null;
		}
		/**
	  	 * 根据Class对象获取表主键id的字段名称
	  	 * @param clz
	  	 * @return
	  	 */
		public  static String  getTablePrimaryId(Class clz){
			try {
				return MyBatisReflectUtil.id(clz.newInstance());
			} catch (InstantiationException | IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
	}
	  	
	  	
}
